package ss.pku.jsa.type.test;
//package jqual.test;
//
//import java.io.BufferedReader;
//import java.io.BufferedWriter;
//import java.io.File;
//import java.io.FileNotFoundException;
//import java.io.FileReader;
//import java.io.FileWriter;
//import java.io.IOException;
//import java.io.InputStream;
//import java.io.InputStreamReader;
//import java.io.OutputStreamWriter;
//import java.io.PrintWriter;
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.Stack;
//
//import javax.xml.parsers.SAXParser;
//import javax.xml.parsers.SAXParserFactory;
//
//import jqual.Analysis;
//import jqual.JqualPlugin;
//
//import org.eclipse.core.resources.IFile;
//import org.eclipse.core.resources.IFolder;
//import org.eclipse.core.resources.IProject;
//import org.eclipse.core.resources.IWorkspaceRoot;
//import org.eclipse.core.runtime.CoreException;
//import org.eclipse.core.runtime.IPath;
//import org.eclipse.core.runtime.IPlatformRunnable;
//import org.eclipse.jdt.core.ICompilationUnit;
//import org.eclipse.jdt.core.IOpenable;
//import org.eclipse.jdt.core.JavaCore;
//import org.xml.sax.Attributes;
//import org.xml.sax.InputSource;
//import org.xml.sax.XMLReader;
//import org.xml.sax.helpers.DefaultHandler;
//
//public class Main implements IPlatformRunnable {
//	static IWorkspaceRoot root = JqualPlugin.getWorkspace().getRoot();
//	static String rootPathPrefix = root.getLocation().toString() + "/";
//	IProject project;
//	int testsRun;
//	int testsPassed;
//	String defaultLattice;
//	Test curTest = null;
//	Stack<Suite> suites;
//	boolean forceAccept;
//
//	public Object run(Object argsObj) throws Exception {
//		try {
//			String proj = System.getProperty("proj");
//			if (proj == null) {
//				System.err.println("Specify project with -Dproj");
//				return null;
//			}
//
//			String forceVal = System.getProperty("force");
//			this.forceAccept = ((forceVal != null) && (forceVal.equals("true")));
//
//			String testfile = System.getProperty("testfile");
//			if (testfile == null) {
//				testfile = "test.xml";
//			}
//
//			this.suites = new Stack();
//			this.suites.push(new Suite());
//
//			JqualPlugin.out.println("Running tests in project " + proj);
//
//			this.project = root.getProject("/" + proj);
//			IFile testXml = this.project.getFile(testfile);
//			if (!testXml.exists()) {
//				System.err.println("Could not open file " + testfile
//						+ " in project " + this.project);
//				return null;
//			}
//
//			if (!testXml.isSynchronized(2))
//				testXml.refreshLocal(2, null);
//			SAXParserFactory spf = SAXParserFactory.newInstance();
//			SAXParser sp = spf.newSAXParser();
//			XMLReader p = sp.getXMLReader();
//			p.setContentHandler(new XMLHandler());
//			InputStream s = testXml.getContents();
//			p.parse(new InputSource(testXml.getContents()));
//			s.close();
//			JqualPlugin.getWorkspace().save(false, null);
//
//			JqualPlugin.out.println("Ran " + this.testsRun + " tests, "
//					+ this.testsPassed + " passed.");
//
//			return null;
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return null;
//	}
//
//	public IOpenable[] getIOpenables(String[] names) {
//		IOpenable[] inputs = new IOpenable[names.length];
//		for (int i = 0; i < names.length; i++) {
//			IFile file = this.project.getFile(names[i]);
//			if (file == null) {
//				System.err.println("Could not open file: " + names[i]);
//				return null;
//			}
//			IOpenable input = (IOpenable) JavaCore.create(file);
//			inputs[i] = input;
//		}
//		return inputs;
//	}
//
//	public IFile getResultsFile(Test test) {
//		String name = test.suite.name + "_" + test.name;
//		IFolder okFolder = this.project.getFolder("ok");
//		return okFolder.getFile(name + ".ok");
//	}
//
//	public void runStandardTest() {
//		JqualPlugin.out.print("Running test " + this.curTest.name + " in "
//				+ this.curTest.suite.name + ":\n");
//
//		this.curTest.suite.apply();
//
//		for (IOpenable file : this.curTest.files) {
//			JqualPlugin.out.println("   "
//					+ ((ICompilationUnit) file).getElementName());
//		}
//
//		IOpenable[] inputs = (IOpenable[]) this.curTest.files
//				.toArray(new IOpenable[this.curTest.files.size()]);
//		if (inputs.length == 0) {
//			return;
//		}
//
//		Analysis analysis = JqualPlugin.analyze(inputs, false);
//
//		IFile ok = getResultsFile(this.curTest);
//		if (ok.exists()) {
//			String old = readResultsText(ok);
//			String results = analysis.declarationsToStringWithQuals();
//			JqualPlugin.out
//					.println(results + "-----------------------------\n");
//
//			if (results.equals(old)) {
//				JqualPlugin.out.println("OK");
//				this.testsPassed += 1;
//			} else {
//				File f = FileBuffers.getSystemFileAtLocation(ok.getLocation());
//				String diffs = compareResultsText(results, f.getAbsolutePath());
//				if (diffs.length() > 0) {
//					JqualPlugin.out
//							.println("Differences between new results and old:\n"
//									+ diffs);
//					try {
//						JqualPlugin.out.print("FAIL (" + this.curTest.name
//								+ ")!  Accept new result [Y/n]? ");
//						String resp = null;
//						if (this.forceAccept) {
//							resp = "y";
//						} else {
//							BufferedReader in = new BufferedReader(
//									new InputStreamReader(System.in));
//							resp = in.readLine();
//						}
//						if ((resp.length() == 0) || (resp.charAt(0) == 'y')
//								|| (resp.charAt(0) == 'Y'))
//							writeResultsText(analysis, ok);
//					} catch (IOException localIOException1) {
//						throw new RuntimeException(
//								"Could not write to results file "
//										+ ok.getName());
//					}
//					JqualPlugin.printlnLog("failedTestResults", "old\n===\n"
//							+ old + "\n\nnew\n===\n" + results);
//				} else {
//					JqualPlugin.out.println("OK");
//					this.testsPassed += 1;
//				}
//			}
//		} else {
//			JqualPlugin.out.print("No previous results available");
//			JqualPlugin.out.print(" Accept new result [Y/n]? ");
//			try {
//				String resp = null;
//				if (this.forceAccept) {
//					resp = "y";
//				} else {
//					BufferedReader in = new BufferedReader(
//							new InputStreamReader(System.in));
//					resp = in.readLine();
//				}
//				if ((resp.length() == 0) || (resp.charAt(0) == 'y')
//						|| (resp.charAt(0) == 'Y')) {
//					ok.create(null, true, null);
//					writeResultsText(analysis, ok);
//				}
//			} catch (IOException e) {
//				JqualPlugin.out.println("Could not create results file "
//						+ ok.getName() + "\n" + e + "\n");
//			} catch (CoreException e) {
//				JqualPlugin.out.println("Could not create results file "
//						+ ok.getName() + "\n" + e + "\n");
//			}
//		}
//		this.testsRun += 1;
//	}
//
//	public static boolean writeResultsText(Analysis results, IFile file) {
//		if (file == null) {
//			throw new IllegalArgumentException("Null file");
//		}
//		String filename = file.getName();
//		try {
//			IPath path = file.getFullPath();
//			JqualPlugin.out.println("path is " + path);
//			File f = FileBuffers.getSystemFileAtLocation(path);
//
//			PrintWriter out = new PrintWriter(new BufferedWriter(
//					new FileWriter(f)));
//			out.print(results.declarationsToStringWithQuals());
//			out.close();
//		} catch (IOException e) {
//			System.err.println("Could not write results to " + filename + ": "
//					+ e + "\n");
//			return false;
//		}
//		return true;
//	}
//
//	public static String readResultsText(IFile file) {
//		StringBuffer results = new StringBuffer();
//		if (file == null) {
//			throw new IllegalArgumentException("null file");
//		}
//		String filename = file.getName();
//		IPath path = file.getFullPath();
//		try {
//			if (!file.isSynchronized(2)) {
//				file.refreshLocal(2, null);
//			}
//			File f = FileBuffers.getSystemFileAtLocation(path);
//			char[] buf = new char['ÿ'];
//			BufferedReader in = new BufferedReader(new FileReader(f));
//			int ct = 0;
//			do {
//				ct = in.read(buf);
//				if (ct <= 0)
//					continue;
//				results.append(buf, 0, ct);
//			} while (ct > 0);
//			in.close();
//		} catch (FileNotFoundException localFileNotFoundException) {
//			JqualPlugin.out.println("New file: " + path);
//			return null;
//		} catch (Exception e) {
//			throw new IllegalArgumentException("Error reading file: "
//					+ filename + " - " + e);
//		}
//		return results.toString();
//	}
//
//	public static String compareResultsText(String newResult,
//			String oldResultPath) {
//		StringBuffer ret = new StringBuffer();
//		try {
//			String cmd = "diff -bwi - " + oldResultPath;
//
//			Process p = Runtime.getRuntime().exec(cmd);
//			PrintWriter out = new PrintWriter(new OutputStreamWriter(
//					p.getOutputStream()));
//
//			out.print(newResult);
//			out.close();
//
//			char[] buf = new char['ÿ'];
//			BufferedReader in = new BufferedReader(new InputStreamReader(
//					p.getInputStream()));
//			int ct = 0;
//			do {
//				ct = in.read(buf);
//				if (ct <= 0)
//					continue;
//				ret.append(buf, 0, ct);
//			} while (ct > 0);
//			in.close();
//
//			StringBuilder diffErr = new StringBuilder();
//			BufferedReader err = new BufferedReader(new InputStreamReader(
//					p.getErrorStream()));
//			ct = 0;
//			do {
//				ct = err.read(buf);
//				if (ct <= 0)
//					continue;
//				diffErr.append(buf, 0, ct);
//			} while (ct > 0);
//			err.close();
//			if (diffErr.length() > 0) {
//				ret.append("\n============ Error output from DIFF: (if any) ===========\n");
//				ret.append(diffErr);
//			}
//		} catch (Exception e) {
//			return "Could not compare with old results: " + e;
//		}
//		return ret.toString();
//	}
//
//	public static String showResults(String newResult, String oldResult) {
//		if (oldResult == null) {
//			return "Old result file is empty.";
//		}
//		if (newResult.equals(oldResult)) {
//			return "<couldn't find any differences...>";
//		}
//		StringBuffer ret = new StringBuffer();
//		ret.append("-------------------------- old results: -------------------------------\n");
//		ret.append(oldResult);
//		ret.append("-------------------------- new results: -------------------------------\n");
//		ret.append(newResult);
//		ret.append("-----------------------------------------------------------------------\n\n");
//		return ret.toString();
//	}
//
//	public String getAnalysisResult(Analysis result) {
//		return result.dumpQTypes() + result.dumpObjects() + result.toString();
//	}
//
//	static class Suite {
//		Map<String, String> prefs;
//		String name;
//
//		Suite() {
//			this.prefs = new HashMap();
//			this.prefs.put("contextSensitive", "false");
//			this.prefs.put("typeClosurePreference", "false");
//			this.prefs.put("includePartialJavaLibraries", "false");
//			this.prefs.put("includeJavaLibraries", "false");
//			this.prefs.put("logInferredTypes", "false");
//			this.prefs.put("useLongQualifierNamesPreference", "true");
//			this.prefs.put("fieldSensitive", "false");
//			this.prefs.put("obeyfieldSensitiveMarkups", "false");
//			this.prefs.put("allowMerge", "false");
//			this.prefs.put("javariAnalysis", "false");
//			this.prefs.put("doFFIAnalysis", "false");
//			this.prefs.put("profilePreference", "false");
//			this.prefs.put("debugPreference", "false");
//			this.prefs.put("logConstraints", "false");
//			this.prefs.put("allowSubtypesInFFIAnalysis", "false");
//			this.prefs.put("latticePreference", "");
//			this.prefs.put("qualsFileForFFIAnalysis", "");
//			this.prefs.put("annotationsFileForFFIAnalysis", "");
//			this.name = "";
//		}
//
//		Suite(String name, Suite s) {
//			this.prefs = new HashMap(s.prefs);
//			if (s.name.length() > 0)
//				this.name = (s.name + "." + name);
//			else
//				this.name = name;
//		}
//
//		void put(String name, String value) {
//			this.prefs.put(name, value);
//		}
//
//		String getStringPref(String name) {
//			String ret = (String) this.prefs.get(name);
//			if (ret == null) {
//				throw new IllegalArgumentException("Unknown Pref " + name);
//			}
//			return ret;
//		}
//
//		boolean getBooleanPref(String name) {
//			boolean ret;
//			try {
//				ret = new Boolean((String) this.prefs.get(name)).booleanValue();
//			} catch (NullPointerException localNullPointerException) {
//				throw new IllegalArgumentException("Unknown Pref " + name);
//			}
//			return ret;
//		}
//
//		void apply() {
//			if (getStringPref("latticePreference").length() == 0)
//				throw new RuntimeException(
//						"You must provide a value for the lattice path.");
//			String ffiAnnotationsPath;
//			if (getBooleanPref("doFFIAnalysis")) {
//				String ffiPath = getStringPref("qualsFileForFFIAnalysis");
//				if ((ffiPath == null) || (ffiPath.length() == 0)) {
//					throw new IllegalArgumentException(
//							"To perform FFI analysis you must specify a qualifier file.");
//				}
//				ffiAnnotationsPath = getStringPref("annotationsFileForFFIAnalysis");
//				if ((ffiAnnotationsPath == null)
//						|| (ffiAnnotationsPath.length() == 0)) {
//					throw new IllegalArgumentException(
//							"To perform FFI analysis you must specify an FFI annotations file.");
//				}
//
//			}
//
//			for (Map.Entry pref : this.prefs.entrySet()) {
//				setPreference((String) pref.getKey(), (String) pref.getValue());
//			}
//
//			JqualPlugin.showEmptyQuals = false;
//		}
//
//		private void setPreference(String name, String value) {
//			if (name.equals("contextSensitive"))
//				JqualPlugin.contextSensitive = new Boolean(value)
//						.booleanValue();
//			else if (name.equals("typeClosurePreference")) {
//				JqualPlugin.useClosure = new Boolean(value).booleanValue();
//			} else if (name.equals("includeJavaLibraries"))
//				JqualPlugin.useJavalib = new Boolean(value).booleanValue();
//			else if (name.equals("logInferredTypes"))
//				JqualPlugin.logInferred = new Boolean(value).booleanValue();
//			else if (name.equals("useLongQualifierNamesPreference"))
//				JqualPlugin.useLongNames = new Boolean(value).booleanValue();
//			else if (name.equals("fieldSensitive"))
//				JqualPlugin.fieldSensitive = new Boolean(value).booleanValue();
//			else if (name.equals("obeyfieldSensitiveMarkups"))
//				JqualPlugin.obeyFSAnnotations = new Boolean(value)
//						.booleanValue();
//			else if (name.equals("allowMerge"))
//				JqualPlugin.allowMerge = new Boolean(value).booleanValue();
//			else if (name.equals("javariAnalysis"))
//				JqualPlugin.inferReadonly = new Boolean(value).booleanValue();
//			else if (name.equals("inferInterned"))
//				JqualPlugin.inferInterned = new Boolean(value).booleanValue();
//			else if (name.equals("doFFIAnalysis"))
//				JqualPlugin.inferOpaque = new Boolean(value).booleanValue();
//			else if (name.equals("allowSubtypesInFFIAnalysis"))
//				JqualPlugin.useFFISubtypes = new Boolean(value).booleanValue();
//			else if (name.equals("debugPreference"))
//				JqualPlugin.debug = new Boolean(value).booleanValue();
//			else if (name.equals("logConstraints"))
//				JqualPlugin.logConstraints = new Boolean(value).booleanValue();
//			else if (name.equals("profilePreference")) {
//				JqualPlugin.profile = new Boolean(value).booleanValue();
//			} else if (!name.equals("directory")) {
//				if (name.equals("latticePreference")) {
//					JqualPlugin.latticePath = Main.rootPathPrefix + value;
//					JqualPlugin.out.println(JqualPlugin.latticePath);
//				} else if (name.equals("qualsFileForFFIAnalysis")) {
//					JqualPlugin.ffiQualsPath = Main.rootPathPrefix + value;
//				} else if (name.equals("annotationsFileForFFIAnalysis")) {
//					JqualPlugin.ffiAnnotationsPath = Main.rootPathPrefix
//							+ value;
//				} else {
//					JqualPlugin.out.println("Unknown preference " + name);
//				}
//			}
//		}
//	}
//
//	private class Test {
//		List<IOpenable> files = new ArrayList();
//		String name;
//		Main.Suite suite;
//		String dirpath;
//
//		Test(String name) {
//			this.name = name;
//			this.suite = ((Main.Suite) Main.this.suites.peek());
//			this.dirpath = this.suite.getStringPref("directory");
//		}
//
//		void addFile(String filename) {
//			filename = filename.trim();
//			if (filename.length() == 0) {
//				return;
//			}
//
//			if (this.name == null) {
//				this.name = filename;
//			}
//			String filepath = this.dirpath + "/" + filename;
//			IFile file = Main.this.project.getFile(filepath);
//			if (file == null)
//				throw new IllegalArgumentException("Could not open file: "
//						+ filepath);
//			IOpenable javaFile = (IOpenable) JavaCore.create(file);
//			if (javaFile == null)
//				throw new IllegalArgumentException("Could not open java file: "
//						+ filepath);
//			this.files.add(javaFile);
//		}
//	}
//
//	public class XMLHandler extends DefaultHandler {
//		boolean inTest = false;
//		boolean inMultiTest = false;
//		String multiName = null;
//
//		public XMLHandler() {
//		}
//
//		public void startElement(String strNamespaceURI, String strLocalName, String strQName, Attributes al) { if (!strQName.equals("tests"))
//         if (strQName.equals("suite")) {
//           null;
//           if ((al.getLength() < 1) || (!al.getQName(0).equals("name")))
//             throw new IllegalArgumentException("first element of suite tag must be 'name'");
//           Main.Suite suite = new Main.Suite(al.getValue(0), (Main.Suite)Main.this.suites.peek());
//           for (int i = 1; i < al.getLength(); i++)
//             suite.put(al.getQName(i), al.getValue(i));
//           Main.this.suites.push(suite);
//         } else if (strQName.equals("test")) {
//           this.inTest = true;
//           String name = null;
//           if (al.getLength() == 1) {
//             if (!al.getQName(0).equals("name"))
//               throw new IllegalArgumentException("test tag can only have single attribute 'name', this has " + al.getQName(0));
//             name = al.getValue(0);
//           } else if (al.getLength() > 1) {
//             throw new IllegalArgumentException("test tag can only have single attribute 'name', this has " + al.getLength());
//           }
//           Main.this.curTest = new Main.Test(Main.this, name);
//         } else if (strQName.equals("multitest")) {
//           this.inMultiTest = true;
//           if ((al.getLength() != 1) || (!al.getQName(0).equals("name"))) {
//             throw new IllegalArgumentException("multitest tag must have single attribute 'name'");
//           }
//           this.multiName = al.getValue(0);
//         } else {
//           throw new IllegalArgumentException("Unknown tag: " + strQName);
//         } }
//
//		public void characters(char[] a, int s, int l) {
//			if (this.inTest) {
//				String filename = new String(a, s, l).trim();
//				Main.this.curTest.addFile(filename);
//			} else if (this.inMultiTest) {
//				String filename = new String(a, s, l).trim();
//
//				if (filename.length() == 0)
//					return;
//				Main.this.curTest = new Main.Test(Main.this, filename);
//				Main.this.curTest.addFile(filename);
//				Main.this.runStandardTest();
//			} else {
//				return;
//			}
//		}
//
//		public void endElement(String strNamespaceURI, String strLocalName,
//				String strQName) {
//			if (!strQName.equals("tests"))
//				if (strQName.equals("suite")) {
//					Main.this.suites.pop();
//				} else if (strQName.equals("test")) {
//					this.inTest = false;
//					Main.this.runStandardTest();
//				} else if (strQName.equals("multitest")) {
//					this.inMultiTest = false;
//				} else {
//					throw new IllegalArgumentException("Unknown tag: "
//							+ strQName);
//				}
//		}
//	}
//}
//
